import json
from django.http import JsonResponse
from django.views.generic import View
from ..models.Literature import Literature
import habanero
import traceback
import pycountry
from Bio import Entrez
from utils.encryptionAndDecryptionUtil import get_useraccount_from_request
from control.models.User import User
from ..models.Author import Author
from ..models.Keyword import Keyword
from ..models.GlobalTables import Language, KeywordType
import re
from datetime import datetime

default_email = "13313817433@163.com"

def code_to_language_name(code: str):
    try:
        lang = pycountry.languages.get(alpha_2=code.lower())
        if lang and hasattr(lang, 'name'):
            return lang.name.split(' (')[0].capitalize()
    except:
        pass
    return 'unknown'

def get_date_from_published(item):
    date = item.get('published', None)
    if date is not None:
        date = date.get('date-parts', None)
        if date is not None:
            return "-".join([str(i) for i in date[0]])
        else:
            return None
    else:
        return None

def get_date_from_issued(item): 
    date = item.get('issued', None)
    if date is not None:
        date = date.get('date-parts', None)
        if date is not None:
            return "-".join([str(i) for i in date[0]])
        else:
            return get_date_from_published(item)
    else:
        return get_date_from_published(item)

def get_date_from_published_print(item):
    date = item.get('published-print', None)
    if date is not None:
        date = date.get('date-parts', None)
        if date is not None:
            return "-".join([str(i) for i in date[0]])
        else:
            return get_date_from_issued(item)
    else:
        return get_date_from_issued(item)

def get_info_from_internet(title, blank_fields):
    res = []
    
    # 初始化CrossRef客户端
    cr = habanero.Crossref()
    # 使用引文名称进行文献检索
    result = cr.works(query=title)
    
    # 检查是否有结果
    if 'message' in result and 'total-results' in result['message'] and result['message']['total-results'] > 0:
        for item in result['message']['items']:
            tmp = []
            
            if "date" in blank_fields:
                pub_date = get_date_from_published_print(item)
                if pub_date is not None:
                    tmp.append({"field_data_index": "date", "field_name": "发表日期", "field_value": pub_date, "is_selected": False, "can_select": True})
            if "DOI" in blank_fields:
                doi = item.get('DOI', None)
                if doi is not None:
                    tmp.append({"field_data_index": "DOI", "field_name": "DOI", "field_value": doi, "is_selected": False, "can_select": True})
            if "language" in blank_fields:
                tmp.append({"field_data_index": "language", "field_name": "语言","field_value": code_to_language_name(item.get('language', None)), "is_selected": False, "can_select": True})
            
            if "net_src" in blank_fields:
                link = item.get('link', None)
                if link is not None:
                    if len(link) > 0:
                        link = link[0].get('URL', None)
                    else:
                        link = None
                else:
                    link = item.get('resource', None)
                    if link is not None:
                        link = link.get('primary', None)
                        if link is not None:
                            link = link.get('URL', None)
                if link is not None:
                    tmp.append({"field_data_index": "net_src", "field_name": "网络链接", "field_value": link, "is_selected": False, "can_select": True})
            
            if "volume" in blank_fields:
                volume = item.get('volume', None)
                if volume is not None:
                    tmp.append({"field_data_index": "volume", "field_name": "卷号", "field_value": volume, "is_selected": False, "can_select": True})
            if "issue" in blank_fields:
                issue = item.get('issue', None)
                if issue is not None:
                    tmp.append({"field_data_index": "issue", "field_name": "期号", "field_value": issue, "is_selected": False, "can_select": True})
            
            if 'authors' in blank_fields:
                authors = item.get('author', None)
                if authors is not None:
                    author_list = []
                    for author in authors:
                        if 'given' in author and 'family' in author:
                            author_list.append(author['family'] + "," + author['given'])
                    if len(author_list) > 0:
                        tmp.append({"field_data_index": "authors", "field_name": "作者列表", "field_value": author_list, "is_selected": False, "can_select": True})
            
            if len(tmp) > 0:
                res_title = item.get('title', None)
                if res_title is not None:
                    res_title = res_title[0] if isinstance(res_title, list) else res_title
                    if title.lower() in res_title.lower():
                        tmp.insert(0, {"field_data_index": "title", "field_name": "引文名称", "field_value": res_title, "is_selected": False, "can_select": False})
                        res.append(tmp)
    
    # 设置邮箱
    Entrez.email = default_email
    # 使用ESearch获取匹配的文献ID列表
    handle = Entrez.esearch(db="pubmed", term=title, retmax=100) # 修改retmax改变返回数据的最大条数
    record = Entrez.read(handle)
    id_list = record["IdList"]
    
    for paper_id in id_list:
        paper_handle = Entrez.efetch(db="pubmed", id=paper_id, retmode="xml")
        paper = Entrez.read(paper_handle)
        paper = paper.get('PubmedArticle', None)
        if paper is not None:
            for p in paper:
                p_data = p.get('MedlineCitation', None)
                if p_data is not None:
                    tmp = []
                    if "keywords" in blank_fields:
                        keywords = p_data.get('KeywordList', None)
                        if keywords is not None and len(keywords) > 0:
                            keywords = [keyword for keyword in keywords[0]]
                            tmp.append({"field_data_index": "keywords", "field_name": "关键词列表", "field_value": keywords, "is_selected": False, "can_select": True})
                    
                    res_p = p_data.get('Article', None)
                    # print(res_p)
                    if res_p is not None:
                        if "abstract" in blank_fields:
                            abstract = res_p.get('Abstract', None)
                            # print(abstract)
                            if abstract is not None:
                                abstract = abstract.get('AbstractText', None)
                                # print(abstract)
                                if abstract is not None and len(abstract) > 0:
                                    abstract = abstract[0]
                                    # print(abstract)
                                    tmp.append({"field_data_index": "abstract", "field_name": "摘要", "field_value": abstract, "is_selected": False, "can_select": True})
                        
                        p_pagination = res_p.get('Pagination', None)
                        # print(p_pagination)
                        if p_pagination is not None:
                            if "first_page" in blank_fields:
                                fp = p_pagination.get('StartPage', None)
                                # print(fp)
                                if fp is not None:
                                    tmp.append({"field_data_index": "first_page", "field_name": "起始页码", "field_value": fp, "is_selected": False, "can_select": True})
                            if "last_page" in blank_fields:
                                lp = p_pagination.get('EndPage', None)
                                # print(lp)
                                if lp is not None:
                                    tmp.append({"field_data_index": "last_page", "field_name": "结束页码", "field_value": lp, "is_selected": False, "can_select": True})
                        
                        if len(tmp) > 0:
                            res_title = res_p.get('ArticleTitle', None)
                            # print(res_title, title)
                            if res_title is not None:
                                if title.lower() in res_title.lower():
                                    tmp.insert(0, {"field_data_index": "title", "field_name": "引文名称", "field_value": res_title, "is_selected": False, "can_select": False})
                                    res.append(tmp)
    
    return res

class LiterSearchBlankFieldsView(View):
    def get(self, request, id):
        res = {"code": 400, "message": "", "data": None}
        try:
            liter = Literature.objects.get(uuid=id)
            data = request.GET
            blank_fields = data.getlist('blank_fields[]', [])
            
            res_data = []
            internet_res = get_info_from_internet(liter.title, blank_fields)
            
            res_data.extend(internet_res)
            
            res["code"] = 200
            res["message"] = "检索成功"
            res["data"] = res_data
        except Exception as e:
            traceback.print_exc()
            res["code"] = 500
            res["message"] = "服务器错误：" + str(e)
        return JsonResponse(res)
    
def parse_date_auto(date_str):
    date_str = date_str.strip()

    if re.fullmatch(r"\d{4}", date_str): # 只有年份
        return f"{date_str}-01-01"
    elif re.fullmatch(r"\d{4}-\d{1,2}", date_str): # 年 + 月（1位或2位）
        try:
            dt = datetime.strptime(date_str, "%Y-%m")
            return dt.strftime("%Y-%m-01")
        except ValueError:
            return None
    elif re.fullmatch(r"\d{4}-\d{1,2}-\d{1,2}", date_str): # 年 + 月 + 日
        try:
            dt = datetime.strptime(date_str, "%Y-%m-%d")
            return dt.strftime("%Y-%m-%d")
        except ValueError:
            return None
    else:
        return None
    
class LiterCompleteView(View):
    def put(self, request, id):
        res = {"code": 400, "message": "", "data": None}
        try:
            liter = Literature.objects.get(uuid=id)
            
            user_name = get_useraccount_from_request(request=request)
            u = User.objects.filter(user_account=user_name)[0]
            data = json.loads(request.body)
            
            # print(data)
            for key in data:
                if key == "authors":
                    authors = data[key]
                    liter.authors.clear()
                    for author in authors:
                        try:
                            author_obj = Author.objects.get(name=author)
                        except:
                            author_obj = Author.objects.create(name=author, creator=u, last_editor=u)
                        liter.authors.add(author_obj.uuid)
                elif key == "keywords":
                    keywords = data[key]
                    liter.keywords.clear()
                    ktp = KeywordType.objects.get(name="Keyword")
                    for keyword in keywords:
                        try:
                            keyword_obj = Keyword.objects.get(kt=ktp, k=keyword)
                        except:
                            keyword_obj = Keyword.objects.create(kt=ktp, k=keyword, creator=u, last_editor=u)
                        liter.keywords.add(keyword_obj.uuid)
                elif key == "language":
                    lang = Language.objects.get(name=data[key])
                    liter.language = lang
                elif key == 'first_page' or key == 'last_page':
                    if data[key].isdigit():
                        setattr(liter, key, int(data[key]))
                elif key == 'date':
                    setattr(liter, key, parse_date_auto(data[key]))
                else:
                    setattr(liter, key, data[key])
            
            liter.last_editor = u
            liter.save()
            res["code"] = 200
            res["message"] = "文献信息补全成功"
            res["data"] = None
        except Exception as e:
            traceback.print_exc()
            res["code"] = 500
            res["message"] = "服务器错误：" + str(e)
        return JsonResponse(res)